﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using Skin2D.Bone;
using System.Windows.Forms;

namespace Skin2D.Control.LogSystem
{
    class ILogEntry
    {
        public virtual void Restore()
        {

        }
    }

    //---------------------------------------------------------------------------------------//
    class PropertyLogEntry : ILogEntry
    {
        public PropertyLogEntry(string ProName, object obj, object val)
        {
            m_prop_name = ProName;
            m_value = val;
            m_object = obj;
        }
       

        public override void Restore()
        {
            Type obj_type = m_object.GetType();

            PropertyInfo info = obj_type.GetProperty(m_prop_name);

            info.SetValue(m_object, m_value, null);
        }

        public string m_prop_name;
        public object m_value;
        public object m_object;
    }
     //---------------------------------------------------------------------------------------//
    class BoneAddLogEntry : ILogEntry
    {
        public BoneAddLogEntry(Bone2D bone,Bone2D new_child)
        {
            m_bone = bone;
            m_newChild = new_child;
        }

        public override void Restore()
        {
            m_bone.RemoveChild(m_newChild);
            MyApplication.m_BoneListTreeView.RemoveBone(m_bone, m_newChild);
        }

        public Bone2D m_bone;
        public Bone2D m_newChild;
    }
    //---------------------------------------------------------------------------------------//
    class BoneRemoveLogEntry : ILogEntry
    {
        public BoneRemoveLogEntry(Bone2D bone, Bone2D remove_child, int child_index)
        {
            m_bone = bone;
            m_removeChild = remove_child;
            m_child_index = child_index;
            m_removeChildNode = MyApplication.m_BoneListTreeView.getTreeNode(m_removeChild);
        }

        public override void Restore()
        {
            m_bone.AddChild(m_removeChild, m_child_index);
            MyApplication.m_BoneListTreeView.ReAddTreeNode(m_bone, m_removeChildNode, m_removeChild, m_child_index);
        }

        public Bone2D m_bone;
        public Bone2D m_removeChild;
        public TreeNode m_removeChildNode;
        public int m_child_index;
    }
    //---------------------------------------------------------------------------------------//
    class EventLog
    {

        public static void AddLog(string ProName, object obj, object val)
        {
            PropertyLogEntry tmp = new PropertyLogEntry(ProName, obj, val);
            m_Stack.Push(tmp);
        }

        public static void AddLogNewBone(Bone2D bone, Bone2D new_child)
        {
            BoneAddLogEntry tmp = new BoneAddLogEntry(bone, new_child);
            m_Stack.Push(tmp);
        }

        public static void AddLogRemoveBone(Bone2D bone, Bone2D remove_child, int child_index)
        {
            BoneRemoveLogEntry tmp = new BoneRemoveLogEntry(bone, remove_child, child_index);
            m_Stack.Push(tmp);
        }

        public static void Undo()
        {
            if (m_Stack.Count == 0)
                return;
            ILogEntry tmp = m_Stack.Pop();
            if (tmp != null)
            {
                tmp.Restore();
                //TTin: Hack to Ignore Undo Change Event
                if(tmp is PropertyLogEntry)
                    m_Stack.Pop();
            }
        }

        static Stack<ILogEntry> m_Stack = new Stack<ILogEntry>();

    }
}
